package cn.sciento.iam.saas.domain.service.observer;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;

import cn.sciento.core.exception.CommonException;
import cn.sciento.iam.domain.entity.Role;
import cn.sciento.iam.domain.entity.Tenant;
import cn.sciento.iam.domain.repository.RoleRepository;
import cn.sciento.iam.domain.service.role.TemplateRoleCreateService;
import cn.sciento.iam.saas.domain.service.TenantObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class TenantRoleObserver implements TenantObserver<List<Role>> {
  private static final Logger LOGGER = LoggerFactory.getLogger(TenantRoleObserver.class);
  
  @Autowired
  private RoleRepository roleRepository;
  
  @Autowired
  private TemplateRoleCreateService templateRoleCreateService;
  
  @Override
  public int order() {
    return 50;
  }
  
  @Override
  public List<Role> tenantCreate(@Nonnull Tenant tenant) {
    LOGGER.info("Start create tenant tpl role, tenantNum is {}", tenant.getTenantNum());
    List<Role> tplRoles = this.roleRepository.selectBuiltInTemplateRole("TENANT_ROLE_TPL");
    Map<Boolean, List<Role>> map = (Map<Boolean, List<Role>>)tplRoles.stream().collect(Collectors.partitioningBy(role -> isTenantAdminTemplateRole(role.getCode())));
    Role tenantAdminRoleTpl = (Role)(map.get(Boolean.TRUE)).stream().findFirst().orElseThrow(() -> new CommonException("hiam.error.role.tplRoleNotFound", new Object[] { "role/organization/default/template/administrator" }));
    Role superTenantAdmin = this.roleRepository.selectOneRoleByCode("role/organization/default/administrator");
    Role tenantAdminRole = this.templateRoleCreateService.createRoleByTpl(superTenantAdmin, tenantAdminRoleTpl, tenant);
    LinkedList<Role> roles = (map.get(Boolean.FALSE)).stream().map(tplRole -> this.templateRoleCreateService.createRoleByTpl(tenantAdminRole, tplRole, tenant)).collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
    roles.addFirst(tenantAdminRole);
    LOGGER.info("[TenantInit - Num={}] -> {}", tenant.getTenantNum(), roles);
    return roles;
  }
  
  protected boolean isTenantAdminTemplateRole(String roleCode) {
    return "role/organization/default/template/administrator".equals(roleCode);
  }
}
